/**
 * 
 */
package com.google.code.cisx.service;

import com.google.code.cisx.client.dto.ProjectViewHelper;
import com.google.code.cisx.client.dto.QueryViewHelper;
import com.google.code.cisx.client.service.RemoteProjectService;
import com.google.code.cisx.client.service.RemoteServiceException;
import com.google.code.cisx.converters.BeanUtilsBeanExtended;
import com.google.code.cisx.model.project.Project;
import com.google.code.cisx.servlets.ServletContextConstants;
import com.google.code.cisx.servlets.StartupServlet;
import com.google.code.cisx.store.api.EntityNotFoundException;
import com.google.code.cisx.store.api.Store;
import com.google.code.cisx.store.api.StoreException;
import com.google.code.cisx.store.jpa.query.ProjectQuery;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.google.inject.Inject;
import com.google.inject.Injector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;

/**
 * @author <a href='mailto:rahul.thakur.xdev@gmail.com'>Rahul Thakur</a>
 * @since 1.0
 * @version $Id: RemoteProjectServiceImpl.java 94 2008-01-05 02:49:05Z
 *          rahul.thakur.xdev $
 */
public class RemoteProjectServiceImpl extends RemoteServiceServlet implements RemoteProjectService {

  /**
   * Serialization Id.
   */
  private static final long serialVersionUID = 4232070826046369084L;

  /**
   * Commons Logging.
   */
  private static final Log log = LogFactory.getLog(RemoteProjectService.class);

  @Inject
  private Store<Project, ProjectQuery<Project>> store;

  /*
   * (non-Javadoc)
   * 
   * @see javax.servlet.GenericServlet#init()
   */
  public void init() throws ServletException {
    super.init();
    if (log.isInfoEnabled())
      log.info("Starting " + getClass().getName());
  }

  /*
   * (non-Javadoc)
   * 
   * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
   */
  @Override
  public void init(ServletConfig config) throws ServletException {
    super.init(config);
    Injector registeredInjector = (Injector) config.getServletContext().getAttribute(
        ServletContextConstants.KEY_GUICE_INJECTOR);
    registeredInjector.injectMembers(this);
  }

  /**
   * {@inheritDoc}
   * 
   * @see com.google.code.cisx.client.service.RemoteProjectService#delete(com.google.code.cisx.client.dto.CommonViewHelper)
   */
  public void delete(ProjectViewHelper entity) throws RemoteServiceException {
    // TODO Auto-generated method stub

  }

  /**
   * {@inheritDoc}
   * 
   * @see com.google.code.cisx.client.service.RemoteProjectService#lookup(java.lang.Class,
   *      java.lang.Long)
   */
  public ProjectViewHelper lookup(Long id) throws RemoteServiceException {
    ProjectViewHelper vObj = null;
    try {
      if (log.isInfoEnabled())
        log.info("Attempting to obtain " + Project.class.getSimpleName()
            + " from underlying database.");

      Project mObj = store.lookup(Project.class, id);

      if (null != mObj) {
        vObj = new ProjectViewHelper();

        if (log.isInfoEnabled())
          log.info("Copying " + Project.class.getSimpleName() + " properties to "
              + ProjectViewHelper.class.getSimpleName());

        BeanUtilsBeanExtended beanUtilsBean = StartupServlet.getBeanUtilsBean();
        Map description = beanUtilsBean.describe(mObj);
        beanUtilsBean.populate(vObj, description);

        if (log.isDebugEnabled())
          log.debug("Copied!");
      } else {
        if (log.isWarnEnabled())
          log.warn("No Project could be looked up for id : " + id);
      }

    } catch (EntityNotFoundException e) {
      throw new RemoteServiceException("Project could not be found for id: " + id, e);
    } catch (StoreException e) {
      throw new RemoteServiceException("Error obtaining project for id: " + id, e);
    } catch (IllegalAccessException e) {
      throw new RemoteServiceException(e);
    } catch (InvocationTargetException e) {
      throw new RemoteServiceException(e);
    } catch (NoSuchMethodException e) {
      throw new RemoteServiceException(e);
    }
    return vObj;
  }

  /**
   * {@inheritDoc}
   * 
   * @see com.google.code.cisx.client.service.RemoteProjectService#query(com.google.code.cisx.client.dto.QueryViewHelper,
   *      int, int)
   */
  public List<ProjectViewHelper> query(QueryViewHelper query, int startIdx, int range)
      throws RemoteServiceException {
    List<ProjectViewHelper> result = new ArrayList<ProjectViewHelper>();

    try {
      if (log.isDebugEnabled())
        log.debug("Converting DTO Query to model query...");

      ProjectQuery<Project> mQuery = new ProjectQuery<Project>();
      {
        BeanUtilsBeanExtended beanUtilsBean = StartupServlet.getBeanUtilsBean();
        Map description = beanUtilsBean.describe(query);
        beanUtilsBean.populate(mQuery, description);
      }

      List<Project> list = store.query(mQuery, startIdx, range);

      if (log.isDebugEnabled())
        log.debug("Obtained " + list.size() + " Projects from underlying database.");

      if (null != list) {
        for (Iterator it = list.iterator(); it.hasNext();) {
          Project mObj = (Project) it.next();
          if (log.isDebugEnabled())
            log.debug("Copying " + Project.class.getSimpleName() + " properties to "
                + ProjectViewHelper.class.getSimpleName());

          BeanUtilsBeanExtended beanUtilsBean = StartupServlet.getBeanUtilsBean();
          Map description = beanUtilsBean.describe(mObj);
          ProjectViewHelper vObj = new ProjectViewHelper();
          beanUtilsBean.populate(vObj, description);

          if (log.isDebugEnabled())
            log.debug("Copied!");

          result.add(vObj);
        }

      } else {
        if (log.isWarnEnabled())
          log.warn("No Projects could be queried.");
      }

    } catch (EntityNotFoundException e) {
      throw new RemoteServiceException("Project could not be queried.", e);
    } catch (StoreException e) {
      throw new RemoteServiceException("Error querying projects.", e);
    } catch (IllegalAccessException e) {
      throw new RemoteServiceException(e);
    } catch (InvocationTargetException e) {
      throw new RemoteServiceException(e);
    } catch (NoSuchMethodException e) {
      throw new RemoteServiceException(e);
    }
    return result;
  }

  /**
   * {@inheritDoc}
   * 
   * @see com.google.code.cisx.client.service.RemoteProjectService#save(com.google.code.cisx.client.dto.CommonViewHelper)
   */
  public ProjectViewHelper save(ProjectViewHelper entity) throws RemoteServiceException {
    // TODO Auto-generated method stub
    return null;
  }

}
